<?php
define( "LANG", 'en' );

/** 
 * fixed_checkdns is a workaround for issues surrounding checkdnsrr in Windows.  In PHP 5.2.x, checkdnsrr
 * did not exist, and (personal) experience calls into question the PHP 5.3.x PHP implementation
 */
if( (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') )
{
	function fixed_checkdns($host, $type='MX') 
	{
		if (empty($host)) { return FALSE; }
		$types=array('A', 'MX', 'NS', 'SOA', 'PTR', 'CNAME', 'AAAA', 'A6', 'SRV', 'NAPTR', 'TXT', 'ANY');
		if (!in_array($type,$types)) {
			user_error("checkdnsrr() Type '$type' not supported", E_USER_WARNING);
			return;
		}
		@exec('nslookup -type='.$type.' '.escapeshellcmd($host), $output);
		foreach($output as $line){
			if (preg_match('/^'.$host.'/',$line)) { return true; }
		}
	}
}
else
{
	function fixed_checkdns( $a, $b )
	{
		return checkdnsrr( $a, $b );
	}
}

$messages  = parse_ini_file( "../languages/" . LANG . "/messages.ini" );
$email     = strtolower( @$_REQUEST[ 'user' ] );
$pass      = @$_REQUEST[ 'pass' ];
$pass_conf = @$_REQUEST[ 'pass_conf' ];

$errors = array();

if( strlen( $email . '' ) == 0 )
{
   $errors[] = $messages[ "email_null" ];
}
elseif( !is_email_valid( $email ) )
{
   $errors[] = $messages[ "email_validation_failed" ];
}
if( strlen( $pass . '' ) == 0 )
{
   $errors[] = $messages[ "password_null" ];
}
// This is honestly arbitrary.
elseif( strlen( $pass ) < 6 || strlen( $pass ) > 16 )
{
   $errors[] = ( ( strlen( $pass ) < 6 )? $messages[ "password_fail_short" ]: $messages[ "password_fail_long" ] ) . ' ' . $messages[ 'password_fail' ];
}

if( strlen( $pass_conf . '' ) == 0 )
{
   $errors[] = $messages[ "password_conf_null" ];
}
elseif( $pass != $pass_conf )
{
   $errors[] = $messages[ "password_match_fail" ];
}
//insert into basic_users( username, password ) values ('test@test.test', 'quack')
function create_pdo()
{
    $config     = parse_ini_file( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'ini/dbsettings.ini' );
    return new PDO( "{$config[ 'dbtype' ]}:dbname={$config[ 'dbname' ]};host={$config[ 'host' ]};", $config[ 'user' ], $config[ 'password' ] );
}

if( count( $errors ) == 0 )
{
   $pdo = create_pdo();
   $email = $pdo->quote( $email );
   $stmt = $pdo->query( "select * from basic_users where username = $email" );
   if( !$stmt )
   {
      $errors[] = $messages[ "database_error" ];
   }
   else
   {
      $res  = $stmt->fetchAll();
      $stmt->closeCursor();
      if( count( $res ) )
      {
         $errors[] = $messages[ "email_dupe" ];
      }  
      else
      {
         // Defaulting active to true for now.
         $stmt = $pdo->prepare( "insert into basic_users( username, password, active ) values (:email, :pass, '1')" );
         $stmt->bindParam( ":email", $email, PDO::PARAM_STR );
         $stmt->bindParam( ":pass",  $pass,  PDO::PARAM_STR );   
         $stmt->execute();   
      }
   } 
}

$hdr = "success.php?rand=" . microtime( true );
if( count( $errors ) != 0 )
{
   $hdr = "form.php?";
   
   // We really shouldn't restore the password.
   if( is_email_valid( $email ) ) $hdr .= "email=" . htmlentities( $email ) . "&";
   
   $hdr .= "rand=" . microtime( true );
   foreach( $errors as $error )
   {
      $hdr .= "&errors[]=$error";
   }
}
header( "Location: $hdr" );

/**
 * This name says it all.  It takes in an email and returns whether it is a valid email
 */
function is_email_valid( $email ) /* Boolean */
{
	$isValid 	= TRUE;
	$atPos		= strrpos( $email, '@' );

	// @ can neither be first, nor can it not be present, loose comparison is fine!
	if( $atPos == FALSE ) return FALSE;
	$local		= substr( $email, 0, $atPos  );
	$domain		= substr( $email, $atPos + 1 );
	$localLen 	= strlen($local);
	$domainLen 	= strlen($domain);
	
	if ( !$domain || !$domainLen || $localLen > 64 )
	{
		// This makes sure that each has a length of >= 1 and the local part is less than 65 characters.
		return FALSE;
	}
	if(!(fixed_checkdns($domain,"MX") || fixed_checkdns($domain,"A")))
	{
		// domain not found in DNS
		return FALSE;
	}

	if (($local[0] == '.' || $local[$localLen-1] == '.') || preg_match('/\\.\\./', $local))
	{
		// local part starts or ends with '.' or contains two consecutive .'s
		return FALSE;
	}
	
	if (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\","",$local)))
	{
		// character not valid in local part unless
		// local part is quoted
		if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$local)))
		{
			return FALSE;
		}
	}
	
	return TRUE;
}

